#!/usr/bin/env python
# -*- coding: UTF-8 -*-

try:
	import sys
	import emblem
	import pygame
	from lib.animateable import *
	from pygame.locals import *
	from lib.utils import *
except ImportError, err:
	print "Could not load %s module." % (err)
	sys.exit(2)

# a few constants
CURSOR_ZERO = 40
CURSOR_RECT = (64, 64)
TILE_SZ = 32
EMBLEM_RECT = (16, 16)
SLIDE_DURATION = 10
'''
Cursor

This is the squarish thing that a user moves and issues commands with.

Note: Tile size is 48. In order to encompass a tile, the Cursor is
8px larger on each side, so its total length is 64. In the creature and
battlefield modules calculations are based on 48. In here we have to
always consider this offset.
'''

class Cursor(pygame.sprite.DirtySprite, Animateable):
	def __init__(self, engine, layer):
		pygame.sprite.DirtySprite.__init__(self)
		Animateable.__init__(self)
		self.set_anim_params(FLD_TILE_SZ)
		self.rect = pygame.rect.Rect((0, 0), CURSOR_RECT)
		self.image = pygame.Surface(self.rect.size).convert()

		self.engine = engine
		self.layers = layer

		# cursor at "0,0" is actually "40,40"
		self.x = CURSOR_ZERO
		self.y = CURSOR_ZERO
		# starting cursor position "12,0"
		self.x += (12 * FLD_TILE_SZ)
		self.y += (0 * FLD_TILE_SZ)
		self.emblem = emblem.Emblem(self.layers, self)
		#self.emblem.set_action(emblem.DEF_MAGIC)

		self.tile_x = 0
		self.tile_y = 0
		self.update_tile_pos()

		self.units = self.layers.get_sprites_from_layer(2)[0]

		screen_rect = pygame.display.get_surface().get_rect()
		# top & left gutters are always 48 px.
		right_gutter = screen_rect.width % 48 or 48
		bottom_gutter = screen_rect.height % 48 or 48
		# cursor_max = full length - cursor offset - field tile size - gutter
		# cursor_max_y = cursor_max - infobar height
		self.max_x = screen_rect.width - 8 - FLD_TILE_SZ - right_gutter
		self.max_y = screen_rect.height - 8 - FLD_TILE_SZ - bottom_gutter - 100

		self.tile = emblem.get_cursor_tile()
		colorkey = self.tile.get_at((0, 0))

		self.image.set_colorkey(colorkey, RLEACCEL)
		self.blank = pygame.Surface((TILE_SZ, TILE_SZ)).convert()
		self.blank.fill(colorkey)

		self.blit_tiles()

		self.mode = "Select"
		self.old_mode = None


		self.show()

	def blit_tiles(self):
		"""
		Blits the Cursor graphic into the sprite
		"""
		self.image.blit(self.tile, ((0,0)))
		self.tile = pygame.transform.flip(self.tile, 1, 0)
		self.image.blit(self.tile, ((TILE_SZ, 0)))
		self.tile = pygame.transform.flip(self.tile, 0, 1)
		self.image.blit(self.tile, ((TILE_SZ, TILE_SZ)))
		self.tile = pygame.transform.flip(self.tile, 1, 0)
		self.image.blit(self.tile, ((0, TILE_SZ)))
		#self.tile = pygame.transform.flip(self.tile, 0, 1)

	def set_mode(self, mode = None):
		"""
		Sets the mode of the cursor
		NA only changes emblem and cursor, not the actual mode
		"""
		if mode == "Attack":
			self.emblem.set_action(emblem.MELEE_ATK)
			self.mode = mode
		elif mode == "Select":
			self.emblem.set_action(None)
			self.mode = mode
		elif mode == "Move":
			self.emblem.set_action(emblem.MOVE)
			self.mode = mode
		elif mode == "NA":
			self.emblem.set_action(emblem.NA)
			self.tile = emblem.get_cursor_tile(1)
			self.blit_tiles()
		elif mode == "Confirm":
			self.old_mode = self.mode
			self.mode = mode
		elif mode == None:
			if self.mode == "Confirm":
				self.set_mode(self.old_mode)
				self.set_mode("Confirm")
			else:
 				self.set_mode(self.mode)
			self.tile = emblem.get_cursor_tile()
			self.blit_tiles()

	def update(self):
		"""
		Updates the Cursor

		Tests if animating - calls slide()
		"""
		if self.is_animating():
			self.slide()
		self.rect.topleft = (self.x, self.y)
		self.update_NA_emblem()

	def update_NA_emblem(self):
		"""
		Updates N/A Emblem (Red Cross) based on underlying tile
		"""
		#test if out of bounds for NA emblem
		if self.mode == "Move":
			x, y = self.get_tile_pos()
			if self.units.test_highlight((x, y)) or self.units[x][y]:
				self.set_mode("NA")
			else:
				self.set_mode(None)
		elif self.mode == "Attack":
			if self.units.test_highlight(self.get_tile_pos()):
				self.set_mode("NA")
			else:
				self.set_mode(None)
		self.dirty = 1



	def c_move(self, key, mod):
		"""
		Moves the cursor - Continous movement using key.get_pressed
		Also checks if out of bounds of screen - returns false
		"""
		if self.mode == "Confirm":
			return 1
		self.mod = mod


		if (key == K_UP and self.y > CURSOR_ZERO):
			if not self.is_animating(1):
				self.animating[1] = key
				self.tile_y -= 1
			return key
		elif (key == K_DOWN and self.y < self.max_y):
			if not self.is_animating(1):
				self.animating[1] = key
				self.tile_y += 1
			return key

		if (key == K_RIGHT and self.x < self.max_x):
			if not self.is_animating(0):
				self.animating[0] = key
				self.tile_x += 1
			return key
		elif (key == K_LEFT and self.x > CURSOR_ZERO):
			if not self.is_animating(0):
				self.animating[0] = key
				self.tile_x -= 1
			return key

		return False

	def update_tile_pos(self):
		"""
		Updates Tile Position Values according to Actual Position Values
		"""
		field = self.layers.get_sprites_from_layer(0)[0]
		self.tile_x = (self.x - CURSOR_ZERO) / 48 + field.get_tile_pos()[0]
		self.tile_y = (self.y - CURSOR_ZERO) / 48 + field.get_tile_pos()[1]

	def get_tile_pos(self):
		"""
		Returns the tile position!
		"""
		field = self.layers.get_sprites_from_layer(0)[0]
		x = self.tile_x + field.get_tile_pos()[0]
		y = self.tile_y + field.get_tile_pos()[1]
		return (x, y)

	def do_action(self, engine):
		"""
		On action key - checks which menu to load, what to call depending on mode
		"""
		(x, y) = self.get_tile_pos()
		if self.mode == "Select":
			if self.units[x][y]:
				self.units[x][y].select()
				engine.load_creature_menu(self.units[x][y])
			else:
				engine.load_sys_menu()
				self.hide()
		elif self.mode == "Attack":
			if self.units[x][y]:
				pass
		elif self.mode == "Move":
			if self.units.walk_unit((x, y)):
				self.set_mode("Confirm")
			# still pending:
			# disable this unit's Move command until next "turn"
			# yeah, yeah, we don't even have turns yet, I know
		elif self.mode == "Confirm" and self.old_mode == "Move":
			#set mode back to select if unit move successful
			if self.units.confirm_move():
				self.set_mode("Select")



	def close(self):
		"""
		Returns cursor to default mode - Select
		"""
		if self.mode == "Confirm":
			self.set_mode(self.old_mode)
			self.units.cancel()
		elif self.mode != "Select":
			self.set_mode("Select")
			self.set_mode()
			self.layers.get_sprites_from_layer(2)[0].disable_highlight()

	def hide(self):
		self.layers.remove(self)

	def show(self):
		self.layers.add(self, layer = 6)
